(* Creme Caramel Compiler (Triple C) - Michele Caceffo - 2008 *)

open Exceptions;;

(* identifiers *)
type ide = Ide of string
(* LDL: Offsets is how far the variable is from the stack pointer [borrowed from intermediate.ml] *)
type offset     =   int

(* LDL: just provide a function for translating an offset into a string *)
let string_of_offset = string_of_int

(* LDL: define the type of record *)
type record =
    Record of ide list

(* LDL: pointer type expressions.
        Note that at this point we would not have weird pointer
        expressions since the parser structurally overcomes them.
*)
type pexp =
    PVar of ide
  | Ref of pexp
  | Deref of pexp
(* arithmetical expressions *)
(* LDL: add the pointer operators related to arithmetical expressions *)
and aexp  =
    N of int
  | R of float
  | Ox of offset (* LDL: add the offset on the stack as a possible value for arithmetical expressions *)
  | PNull (* LDL: pointer NULL *)
  | Var of ide
  (* LDL: note that an arithmetic expression is claimed to be whatever a pexpr here, but we are granted
     by the parser to have dereferencing operators only
  *)
  | P of pexp
  | Rec of record (* LDL: an arithmetical expression could be a record *)
  | Vec of ide * aexp
  | Mat of ide * aexp * aexp
  | Sum of aexp * aexp
  | Sub of aexp * aexp
  | Mul of aexp * aexp
  | Div of aexp * aexp
  | FCall of ide * actual list (* LDL: modified: aexp list <-> actual list *)
(* boolean expressions *)
and bexp =
    B of bool
  | Equ of aexp * aexp
  | LE of aexp * aexp
  | LT of aexp * aexp
  | Not of bexp
  | And of bexp * bexp
  | Or of bexp * bexp
(* LDL: since we want to pass pointers as parameters to function then
        we have to create a etherogeneous type for the actual parameters
*)
and actual = ParamAexp of aexp | ParamPexp of pexp

(* left expressions *)
(* LDL: add dereferenced pointer variables to the lexp type.
        Note that a left expression is claimed to be whatever a pexpr here,
        but we are granted by the parser not to have referencing operators.
*)
type lexp =
    LVar of ide
  | LPexpr of pexp
  | LRec of record (* LDL: also add the record left expression *)
  | LVec of ide * aexp
  | LMat of ide * aexp * aexp

(* commands *)
(* LDL: add the assignment of a pointer expression to the commands *)
type cmd =
    Ass of lexp * aexp
  | PAss of lexp * pexp
  | Blk of cmd list
  | Ite of bexp * cmd * cmd
  | While of bexp * cmd
  | Repeat of cmd * bexp
  | For of ide * aexp * aexp * cmd
  | Write of aexp
  | PCall of ide * actual list (* LDL: modified: aexp list <-> actual list *)

(* declarations *)
(* LDL: add the user constructed types *)
type usrType = 
    UsrRecord of record

type bType = Int
             | Float
	     | UsrType of usrType

(* LDL: --------------------------------------------------------------------- *)

(* LDL: add the Pointer as a type for pointer expressions.
        Note that even if Pointer can possibly be applied on any gType,
         the parser structurally grant us not to have Vector nor Matrix as root
         for the subtree. This it a bit dirty choice but it is also practical
         and fine with a future implementation where also Vectors and Matrices
         might accomplish this role.
 *)
type gType =
    Basic of bType
  | Pointer of gType
  | Vector of int * bType
  | Matrix of int * int * bType

(* LDL: field of a record type definition *)
type trecord_field =
    TRecordField of ide * bType

(* LDL: possible types that will follow the type keyword *)
type type_ =
    TRecord of trecord_field list

(* LDL: root node for the type declaration subtree *)
type type_def =
    TypeDef of ide * type_

type dec = Dec of ide * gType

(* procedures / functions *)
(* LDL: here we extend the type of parameters from bType to gType.
        Here a Vector or a Matrix cannot ever occur becouse of the parser structure.
*)
type param = Par of ide * gType

(* LDL: note that we did not modify the ret type since we do not want pointers to be
         returned from functions
*)
type ret = Ret of bType

type proc = Proc of ide * param list * dec list * cmd
            | Func of ide * param list * ret * dec list * cmd

(* programs *)
(* LDL: add the types list here *)
type program = Program of type_def list * dec list * proc list * cmd | SynError
